package pkg

import (
	"crypto/rand"
	"fmt"
	"math/big"
)

// generate a random string with alphanumeric characters.
// [0-9][a-z][A-Z]
func RandomAlphanumericString(n int) (string, error) {
	max := big.NewInt(62)
	b := make([]byte, n)

	for i := 0; i < n; i++ {
		randInt, err := rand.Int(rand.Reader, max)
		if err != nil {
			return "", err
		}
		switch {
		case randInt.Int64() < 10:
			b[i] = byte(randInt.Int64() + '0')
		case randInt.Int64() < 36:
			b[i] = byte(randInt.Int64() + 'a' - 10)
		default:
			b[i] = byte(randInt.Int64() + 'A' - 36)
		}
	}
	return string(b), nil
}

// generate a random string with printable characters.
// ASCII [33-126]
func RandomPrintableString(n int) (string, error) {
	max := big.NewInt(94)
	b := make([]byte, n)

	for i := 0; i < n; i++ {
		randInt, err := rand.Int(rand.Reader, max)
		if err != nil {
			return string(b), err
		}
		b[i] = byte(randInt.Int64() + 33)
	}
	return string(b), nil
}

// SizeToAutoUnit converts a float64 size to a string with appropriate unit.
func SizeToAutoUnit(size float64) string {
	if size < 1000 {
		return fmt.Sprintf("%.2fB", size)
	}
	const units = "KMGTPEZYBN"
	var i int
	for i = 0; i < len(units) && size >= 1000; i++ {
		size /= 1000
	}
	return fmt.Sprintf("%.2f%cB", size, units[i-1])
}
